# 标签化处理
import numpy as np
import pandas as pd

from sklearn.preprocessing import LabelEncoder, OneHotEncoder

data = pd.read_csv('datasets_ML2/iris.txt', header=None)
x = data.iloc[:, :-1]
y = data.iloc[:, -1:]
print(y)

label = LabelEncoder()  # 将字符串信息变为数字分类
y_label = label.fit_transform(y)
print(y_label)

onehot = OneHotEncoder()  # 前提，你的标签必须是数字化格式
y_onehot = onehot.fit_transform(y_label.reshape(-1, 1))

print(y_onehot.toarray())  #toarray才能转换onehotencoding

#  ======== pca
x = x - x.mean(axis=0)
print(x.shape)

cov_mat = np.dot(x.T, x) / len(x)

U, S, V = np.linalg.svd(cov_mat)
print(S)

k = 2
P = V[:k, :].T

z = np.dot(x, P)

import matplotlib.pyplot as plt
# y = np.argmax(y, axis=1)
plt.scatter(z[:, 0], z[:, 1], c=y_label)
plt.show()

# classification
Z = np.insert(z, 0, 1, axis=1)
m, n = Z.shape

def mapFeature(x1, x2):
    degraee = 6
    out = np.ones((len(x1), 1))
    for i in range(1, degraee + 1):
        for j in range(0, i + 1):
            x1_term = x1 ** (i - j)
            x2_term = x2 ** j
            term = x1_term * x2_term
            out = np.hstack((out, term.reshape(-1, 1)))
    return out

print("Z", Z[:3, :], Z.shape)
mapZ = mapFeature(Z[:, 1], Z[:, 2])
print("mapZ", mapZ[:3, :], mapZ.shape)

from sklearn.linear_model import LogisticRegression
model_lr = LogisticRegression()
model_lr.fit(mapZ[:, 1:], y_label)

print(model_lr.score(mapZ[:, 1:], y_label))
print(model_lr.intercept_.shape, model_lr.coef_.shape)

theta = np.c_[model_lr.intercept_, model_lr.coef_]
theta = theta.T
print(theta.shape)

# plot boundary
z1_val = np.linspace(np.min(Z[:, 1])-0.2, np.max(Z[:, 1])+0.2, 200)
z2_val = np.linspace(np.min(Z[:, 2])-0.2, np.max(Z[:, 2])+0.2, 200)
def plotBoundary(theta):
    hvals = np.zeros((len(z1_val), len(z2_val)))
    for i in range(len(z1_val)):
        for j in range(len(z2_val)):
            x = np.array(mapFeature(z1_val[i].reshape(1,-1), z2_val[j].reshape(1,-1)))
            h = 1 / (1+np.exp(-np.dot(x, theta)))
            hvals[i][j] = np.argmax(h, axis=1)
    hvals = hvals.T
    plt.contour(z1_val, z2_val, hvals)
    plt.title("Decision Boundary")

plotBoundary(theta)
plt.scatter(z[:, 0], z[:, 1], c=y_label)
plt.legend()
plt.show()
